//
//  UserManger.swift
//
//  Created by Kipp Dev on 2018/1/2.
//  Copyright © 2018年 Kipp. All rights reserved.
//

// swiftlint:disable identifier_name

import Foundation
import HandyJSON

let Preferences = UserManager.instance

final class UserManager {
    static let instance = UserManager()
    let defaults = UserDefaults.standard
    private init() {
        registerDefaultPreferences()
    }

    private func registerDefaultPreferences() {
        let defaultValues: [String: Any] = defaultPreferences.reduce([:]) {
            var dictionary = $0
            dictionary[$1.key.rawValue] = $1.value
            return dictionary
        }
        defaults.register(defaults: defaultValues)
    }
}

extension UserManager {
    subscript(key: PreferenceKey<Any>) -> Any? {
        get { return defaults.object(forKey: key.rawValue) }
        set { defaults.set(newValue, forKey: key.rawValue) }
    }

    subscript(key: PreferenceKey<URL>) -> URL? {
        get { return defaults.url(forKey: key.rawValue) }
        set { defaults.set(newValue, forKey: key.rawValue) }
    }

    subscript(key: PreferenceKey<[Any]>) -> [Any]? {
        get { return defaults.array(forKey: key.rawValue) }
        set { defaults.set(newValue, forKey: key.rawValue) }
    }

    subscript(key: PreferenceKey<[String: Any]>) -> [String: Any]? {
        get { return defaults.dictionary(forKey: key.rawValue) }
        set { defaults.set(newValue, forKey: key.rawValue) }
    }

    subscript(key: PreferenceKey<String>) -> String? {
        get { return defaults.string(forKey: key.rawValue) }
        set { defaults.set(newValue, forKey: key.rawValue) }
    }

    subscript(key: PreferenceKey<[String]>) -> [String]? {
        get { return defaults.stringArray(forKey: key.rawValue) }
        set { defaults.set(newValue, forKey: key.rawValue) }
    }

    subscript(key: PreferenceKey<Data>) -> Data? {
        get { return defaults.data(forKey: key.rawValue) }
        set { defaults.set(newValue, forKey: key.rawValue) }
    }

    subscript(key: PreferenceKey<Bool>) -> Bool {
        get { return defaults.bool(forKey: key.rawValue) }
        set { defaults.set(newValue, forKey: key.rawValue) }
    }

    subscript(key: PreferenceKey<Int>) -> Int {
        get { return defaults.integer(forKey: key.rawValue) }
        set { defaults.set(newValue, forKey: key.rawValue) }
    }

    subscript(key: PreferenceKey<Float>) -> Float {
        get { return defaults.float(forKey: key.rawValue) }
        set { defaults.set(newValue, forKey: key.rawValue) }
    }

    subscript(key: PreferenceKey<Double>) -> Double {
        get { return defaults.double(forKey: key.rawValue) }
        set { defaults.set(newValue, forKey: key.rawValue) }
    }

    /// 存取用户信息
    ///
    /// - Parameter key: .userInfo
    subscript(key: PreferenceKey<UserInfo>) -> UserInfo? {
        get { ///获取用户信息，如果用户 id 为空字符串，则判定没有用户信息
            if let data = defaults.dictionary(forKey: key.rawValue) {
                return UserInfo.deserialize(from: data)!
            }
            return UserInfo()
        }
        set {
            /// 设置用户信息，如果设置的是 nil 则默认新创建一个空的 UserInfo 类来存
            if let data = newValue {
                defaults.set(data.toJSON(), forKey: key.rawValue)
            } else {
                defaults.set(UserInfo().toJSON(), forKey: key.rawValue)
            }
        }
    }
}

final class PreferenceKey<T>: PreferenceKeys { }

class PreferenceKeys: RawRepresentable, Hashable {
    let rawValue: String

    required init!(rawValue: String) {
        self.rawValue = rawValue
    }

    convenience init(_ key: String) {
        self.init(rawValue: key)
    }

    var hashValue: Int {
        return rawValue.hashValue
    }
}

extension PreferenceKeys {
    static let clientDigest = PreferenceKey<String>("ClientDigest")
    static let username = PreferenceKey<String>("Username")
    static let launchAtLogin = PreferenceKey<Bool>("LaunchAtLogin")
    static let WiFiOnly = PreferenceKey<Bool>("WiFiOnly")///仅WiFi下使用
    static let NetworkStatusChanges = PreferenceKey<Bool>("NetworkStatusChanges")///网络切换提醒
    static let launchCount = PreferenceKey<Int>("LaunchCount")
    static let userInfo = PreferenceKey<UserInfo>("UserInfo")
    static let launchImg = PreferenceKey<Data>("launchImg")
    static let token = PreferenceKey<String>("token")
    static let firstLaunch = PreferenceKey<Bool>("firstLaunch")
}

let defaultPreferences: [PreferenceKeys: Any] = [
        .clientDigest: "",
        .username: "",
        .launchAtLogin: false,
        .launchCount: 0,
        .userInfo: UserInfo().toJSON()!,
        .launchImg: Data.init(),
        .WiFiOnly: false,
        .NetworkStatusChanges: true,
        .firstLaunch: true
]
